using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace RideMe.Core
{
    public abstract class ProcessBase
    {

        public event EventHandler<DataReceivedEventArgs> OutputReceived;
        public event EventHandler Completed;
        public event EventHandler<DataReceivedEventArgs> ErrorReceived;

        /// <summary>
        /// Raises the output received event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.Diagnostics.DataReceivedEventArgs"/> instance containing the event data.</param>
        protected virtual void OnOutputReceived(DataReceivedEventArgs e)
        {
            if (OutputReceived != null)
            {
                OutputReceived(this, e);
            }
        }

        /// <summary>
        /// Raises the completed event.
        /// </summary>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnCompleted(EventArgs e)
        {
            if (Completed != null)
            {
                Completed(this, e);
            }
        }

        protected virtual void OnErrorReceived(DataReceivedEventArgs e)
        {
            if (ErrorReceived != null)
            {
                ErrorReceived(this, e);
            }
        }

        private Process _targetProcess;

        public Process TargetProcess
        {
            get { return _targetProcess; }
            set { _targetProcess = value; }
        }


        /// <summary>
        /// Creates the command.
        /// </summary>
        /// <returns></returns>
        protected ProcessExecutor CreateCommand()
        {
            ProcessExecutor command = new ProcessExecutor();

            _targetProcess = command.Proc;

            _targetProcess.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
            _targetProcess.Exited += new EventHandler(process_Exited);
            _targetProcess.ErrorDataReceived += new DataReceivedEventHandler(_targetProcess_ErrorDataReceived);

            return command;
        }

        public abstract void RunCommand(string arguments, bool redirectStandardError);

        /// <summary>
        /// Handles the OutputDataReceived event of the process control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="outLine">The <see cref="T:System.Diagnostics.DataReceivedEventArgs"/> instance containing the event data.</param>
        private void process_OutputDataReceived(object sender, DataReceivedEventArgs outLine)
        {
            if (!string.IsNullOrEmpty(outLine.Data))
            {
                OnOutputReceived(outLine);
            }
        }

        /// <summary>
        /// Handles the Exited event of the process control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void process_Exited(object sender, EventArgs e)
        {
            OnCompleted(e);

            /*
             * Error output is read while the program is running as it can occur anytime, so I think this is no longer needed
            try
            {
                if ((_targetProcess.HasExited) && (_targetProcess.ExitCode != 0))
                {
                    if (_targetProcess.StartInfo.RedirectStandardError)
                    {
                        _targetProcess.BeginErrorReadLine();
                    }
                }
            }
            catch { }
             */
        }

        private void _targetProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                OnErrorReceived(e);
            }
        }
    }
}
